package schame使用xsd;

复杂的类型

【XSD 复合元素】

复合元素包含了其他的元素及/或属性。

●什么是复合元素？
复合元素指包含其他元素及/或属性的 XML 元素。

有四种类型的复合元素：
▪空元素
▪包含其他元素的元素
▪仅包含文本的元素
▪包含元素和文本的元素
注释：上述元素均可包含属性！

●复合元素的例子
1)复合元素，"product"，是空的：<product pid="1345"/>

2)复合元素，"employee"，仅包含其他元素：
<employee>
	<firstname>John</firstname>
	<lastname>Smith</lastname>
</employee>

3)复合元素，"food"，仅包含文本：<food type="dessert">Ice cream</food>

4)复合元素，"description"，包含元素和文本：
<description>
	It happened on <date lang="norwegian">03.03.99</date> ....
</description>

●如何定义复合元素？
请看这个复合 XML 元素，"employee"，仅包含其他元素：

<employee>
	<firstname>John</firstname>
	<lastname>Smith</lastname>
</employee>
在 XML Schema 中，我们有两种方式来定义复合元素：

1. 通过命名此元素，可直接对"employee"元素进行声明，就像这样：
<xs:element name="employee">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
假如您使用上面所描述的方法，那么仅有 "employee" 可使用所规定的复合类型。请注意其子元素，"firstname" 以及 "lastname"，被包围在指示
器 <sequence>中。这意味着子元素必须以它们被声明的次序出现。您会在 XSD 指示器 这一节学习更多有关指示器的知识。

2. "employee" 元素可以使用 type 属性，这个属性的作用是引用要使用的复合类型的名称：
<xs:element name="employee" type="personinfo"/>

<xs:complexType name="personinfo">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:complexType>
如果您使用了上面所描述的方法，那么若干元素均可以使用相同的复合类型，比如这样：

<xs:element name="employee" type="personinfo"/>
<xs:element name="student" type="personinfo"/>
<xs:element name="member" type="personinfo"/>

<xs:complexType name="personinfo">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:complexType>
您也可以在已有的复合元素之上以某个复合元素为基础，然后添加一些元素，就像这样：

<xs:element name="employee" type="fullpersoninfo"/>

<xs:complexType name="personinfo">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="fullpersoninfo">
  <xs:complexContent>
    <xs:extension base="personinfo">
      <xs:sequence>
        <xs:element name="address" type="xs:string"/>
        <xs:element name="city" type="xs:string"/>
        <xs:element name="country" type="xs:string"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>


【XSD 复合空元素】

空的复合元素不能包含内容，只能含有属性。

●复合空元素：
一个空的 XML 元素：<product prodid="1345" />
上面的 "product" 元素根本没有内容。为了定义无内容的类型，我们就必须声明一个在其内容中只能包含元素的类型，但是实际上我们并不会声明任何元素，比如这样：

<xs:element name="product">
  <xs:complexType>
    <xs:complexContent>
      <xs:restriction base="xs:integer">
        <xs:attribute name="prodid" type="xs:positiveInteger"/>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>
</xs:element>
在上面的例子中，我们定义了一个带有复合内容的复合类型。complexContent 元素给出的信号是，我们打算限定或者拓展某个复合类型的内容模型，而 integer 限定则声明了
一个属性但不会引入任何的元素内容。

不过，也可以更加紧凑地声明此 "product" 元素：

<xs:element name="product">
  <xs:complexType>
    <xs:attribute name="prodid" type="xs:positiveInteger"/>
  </xs:complexType>
</xs:element>
或者您可以为一个 complexType 元素起一个名字，然后为 "product" 元素设置一个 type 属性并引用这个 complexType 名称（通过使用此方法，若干个元素均可引用
相同的复合类型）：

<xs:element name="product" type="prodtype"/>

<xs:complexType name="prodtype">
  <xs:attribute name="prodid" type="xs:positiveInteger"/>
</xs:complexType>


【XSD 复合类型 - 仅含元素】

“仅含元素”的复合类型元素是只能包含其他元素的元素。

●复合类型仅包含元素
XML 元素，"person"，仅包含其他的元素：

<person>
	<firstname>John</firstname>
	<lastname>Smith</lastname>
</person>
您可在 schema 中这样定义 "person" 元素：

<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
请留意这个 <xs:sequence>。它意味着被定义的元素必须按上面的次序出现在 "person" 元素中。
或者您可以为 complexType 元素设定一个名称，并让 "person" 元素的 type 属性来引用此名称（如使用此方法，若干元素均可引用相同的复合类型）：

<xs:element name="person" type="persontype"/>

<xs:complexType name="persontype">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:complexType>


【XSD 仅含文本复合元素】
仅含文本的复合元素可包含文本和属性。如：复合元素，"food"，仅包含文本：<food type="dessert">Ice cream</food>

●仅含文本的复合元素
此类型仅包含简易的内容（文本和属性），因此我们要向此内容添加 simpleContent 元素。当使用简易内容时，我们就必须在 simpleContent 元素内定义扩展或限定，就
像这样：

<xs:element name="某个名称">
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base="basetype">
        ....
        ....
      </xs:extension>     
    </xs:simpleContent>
  </xs:complexType>
</xs:element>
或者：

<xs:element name="某个名称">
  <xs:complexType>
    <xs:simpleContent>
      <xs:restriction base="basetype">
        ....
        ....
      </xs:restriction>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>
提示：请使用 extension 或 restriction 元素来扩展或限制元素的基本简易类型。

这里有一个 XML 元素的例子，"shoesize"，其中仅包含文本：<shoesize country="france">35</shoesize>

下面这个例子声明了一个复合类型，其内容被定义为整数值，并且 "shoesize" 元素含有名为 "country" 的属性：

<xs:element name="shoesize">
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base="xs:integer">
        <xs:attribute name="country" type="xs:string" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>

我们也可为 complexType 元素设定一个名称，并让 "shoesize" 元素的 type 属性来引用此名称（通过使用此方法，若干元素均可引用相同的复合类型）：

<xs:element name="shoesize" type="shoetype"/>

<xs:complexType name="shoetype">
  <xs:simpleContent>
    <xs:extension base="xs:integer">
      <xs:attribute name="country" type="xs:string" />
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>


【XSD 带有混合内容的复合类型】
混合的复合类型可包含属性、元素以及文本。

●带有混合内容的复合类型
XML 元素，"letter"，含有文本以及其他元素：

<letter>
	Dear Mr.<name>John Smith</name>.
	Your order <orderid>1032</orderid>
	will be shipped on <shipdate>2001-07-13</shipdate>.
</letter>
下面这个 schema 声明了这个 "letter" 元素：

<xs:element name="letter">
  <xs:complexType mixed="true">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="orderid" type="xs:positiveInteger"/>
      <xs:element name="shipdate" type="xs:date"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
注释：为了使字符数据可以出现在 "letter" 的子元素之间，mixed 属性必须被设置为 "true"。<xs:sequence> 标签 (name、orderid 以及 shipdate ) 意味着
被定义的元素必须依次出现在 "letter" 元素内部。

我们也可以为 complexType 元素起一个名字，并让 "letter" 元素的 type 属性引用 complexType 的这个名称（通过这个方法，若干元素均可引用同一个复合类型）：

<xs:element name="letter" type="lettertype"/>

<xs:complexType name="lettertype" mixed="true">
  <xs:sequence>
    <xs:element name="name" type="xs:string"/>
    <xs:element name="orderid" type="xs:positiveInteger"/>
    <xs:element name="shipdate" type="xs:date"/>
  </xs:sequence>
</xs:complexType>


【XSD 复合类型指示器】

通过指示器，我们可以控制在文档中使用元素的方式。

●指示器
有七种指示器：

◆Order 指示器：
	▪All
	▪Choice
	▪Sequence
◆Occurrence 指示器：
	▪maxOccurs
	▪minOccurs
◆Group 指示器：
	▪Group name
	▪attributeGroup name

●Order 指示器
Order 指示器用于定义元素的顺序。

▪All 指示器
<all> 指示器规定子元素可以按照任意顺序出现，且每个子元素必须只出现一次：

<xs:element name="person">
  <xs:complexType>
    <xs:all>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
    </xs:all>
  </xs:complexType>
</xs:element>
注释：当使用 <all> 指示器时，你可以把<minOccurs>设置为 0 或者 1，而只能把<maxOccurs>指示器设置为 1（稍后将讲解 <minOccurs> 以及 <maxOccurs>）。

▪Choice 指示器
<choice> 指示器规定可出现某个子元素或者可出现另外一个子元素（非此即彼）：

<xs:element name="person">
  <xs:complexType>
    <xs:choice>
      <xs:element name="employee" type="employee"/>
      <xs:element name="member" type="member"/>
    </xs:choice>
  </xs:complexType>
</xs:element>
提示：如需设置子元素出现任意次数，可将 <maxOccurs> （稍后会讲解）设置为 unbounded（无限次）。

▪Sequence 指示器
<sequence> 规定子元素必须按照特定的顺序出现：

<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

●Occurrence 指示器
Occurrence 指示器用于定义某个元素出现的频率。

注释：对于所有的 "Order" 和 "Group" 指示器（any、all、choice、sequence、group name 以及 group reference），其中的 maxOccurs 以
及 minOccurs 的默认值均为 1。

▪maxOccurs 指示器
<maxOccurs> 指示器可规定某个元素可出现的最大次数：

<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="full_name" type="xs:string"/>
      <xs:element name="child_name" type="xs:string" maxOccurs="10"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
上面的例子表明，子元素 "child_name" 可在 "person" 元素中最少出现一次（其中 minOccurs 的默认值是 1），最多出现 10 次。

▪minOccurs 指示器
<minOccurs> 指示器可规定某个元素能够出现的最小次数：

<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="full_name" type="xs:string"/>
      <xs:element name="child_name" type="xs:string" maxOccurs="10" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
上面的例子表明，子元素 "child_name" 可在 "person" 元素中出现最少 0 次，最多出现 10 次。

提示：如需使某个元素的出现次数不受限制，请使用 maxOccurs="unbounded" 这个声明：

一个实际的例子：
名为 "Myfamily.xml" 的 XML 文件：

<?xml version="1.0" encoding="ISO-8859-1"?>

<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="family.xsd">

  <person>
	 <full_name>Tony Smith</full_name>
	 <child_name>Cecilie</child_name>
  </person>

  <person>
	 <full_name>David Smith</full_name>
	 <child_name>Jogn</child_name>
	 <child_name>mike</child_name>
	 <child_name>kyle</child_name>
	 <child_name>mary</child_name>
  </person>

  <person>
	 <full_name>Michael Smith</full_name>
  </person>

</persons>
上面这个 XML 文件含有一个名为 "persons" 的根元素。在这个根元素内部，我们定义了三个 "person" 元素。每个 "person" 元素必须含有一个 "full_name" 元
素，同时它可以包含多至 5 个 "child_name" 元素。

这是schema文件"family.xsd"：

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

<xs:element name="persons">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="person" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="full_name" type="xs:string"/>
            <xs:element name="child_name" type="xs:string" minOccurs="0" maxOccurs="5"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

</xs:schema>

●Group 指示器
Group 指示器用于定义相关的数批元素。

▪元素组
元素组通过 group 声明进行定义：

<xs:group name="组名称">
  ...
</xs:group>
您必须在 group 声明内部定义一个 all、choice 或者 sequence 元素。下面这个例子定义了名为 "persongroup" 的 group，它定义了必须按照精确的顺序出现的一
组元素：

<xs:group name="persongroup">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
    <xs:element name="birthday" type="xs:date"/>
  </xs:sequence>
</xs:group>
在您把 group 定义完毕以后，就可以在另一个定义中引用它了：

<xs:group name="persongroup">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
    <xs:element name="birthday" type="xs:date"/>
  </xs:sequence>
</xs:group>

<xs:element name="person" type="personinfo"/>

<xs:complexType name="personinfo">
  <xs:sequence>
    <xs:group ref="persongroup"/>
    <xs:element name="country" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

▪属性组
属性组通过 attributeGroup 声明来进行定义：

<xs:attributeGroup name="组名称">
  ...
</xs:attributeGroup>
下面这个例子定义了名为 "personattrgroup" 的一个属性组：

<xs:attributeGroup name="personattrgroup">
  <xs:attribute name="firstname" type="xs:string"/>
  <xs:attribute name="lastname" type="xs:string"/>
  <xs:attribute name="birthday" type="xs:date"/>
</xs:attributeGroup>
在您已定义完毕属性组之后，就可以在另一个定义中引用它了，就像这样：

<xs:attributeGroup name="personattrgroup">
  <xs:attribute name="firstname" type="xs:string"/>
  <xs:attribute name="lastname" type="xs:string"/>
  <xs:attribute name="birthday" type="xs:date"/>
</xs:attributeGroup>

<xs:element name="person">
  <xs:complexType>
    <xs:attributeGroup ref="personattrgroup"/>
  </xs:complexType>
</xs:element>


【XSD <any> 元素】

<any> 元素使我们有能力通过未被 schema 规定的元素来拓展 XML 文档！

●<any> 元素
<any> 元素使我们有能力通过未被 schema 规定的元素来拓展 XML 文档！

下面这个例子是从名为 "family.xsd" 的 XML schema 中引用的片段。它展示了一个针对 "person" 元素的声明。通过使用 <any> 元素，我们可以通过任何元
素（在 <lastname> 之后）扩展 "person" 的内容：

<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
      <xs:any minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
现在，我们希望使用 "children" 元素来扩展 "person" 元素。这此种情况下我们就可以这么做，即使以上这个 schema 的作者没有声明任何 "children" 元素。

请看这个 schema 文件，名为 "children.xsd"：

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">

<xs:element name="children">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="childname" type="xs:string"
      maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

</xs:schema>
下面这个 XML 文件（名为 "Myfamily.xml"），使用了来自两个不同的 schema 中的成分，"family.xsd" 和 "children.xsd"：

<?xml version="1.0" encoding="ISO-8859-1"?>

<persons xmlns="http://www.microsoft.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.microsoft.com family.xsd
http://www.w3school.com.cn children.xsd">

  <person>
	 <firstname>David</firstname>
	 <lastname>Smith</lastname>
	 <children>
	 	<childname>mike</childname>
	 </children>
  </person>

  <person>
    <firstname>Tony</firstname>
    <lastname>Smith</lastname>
  </person>

</persons>
上面这个 XML 文件是有效的，这是由于 schema "family.xsd" 允许我们通过在 "lastname" 元素后的可选元素来扩展 "person" 元素。

<any> 和 <anyAttribute> 均可用于制作可扩展的文档！它们使文档有能力包含未在主 XML schema 中声明过的附加元素。


【XSD <anyAttribute> 元素】

<anyAttribute> 元素使我们有能力通过未被 schema 规定的属性来扩展 XML 文档！

●<anyAttribute> 元素
<anyAttribute> 元素使我们有能力通过未被 schema 规定的属性来扩展 XML 文档！

下面的例子是来自名为 "family.xsd" 的 XML schema 的一个片段。它为我们展示了针对 "person" 元素的一个声明。通过使用 <anyAttribute> 元素，我们就
可以向 "person" 元素添加任意数量的属性：

<xs:element name="person">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
    </xs:sequence>
    <xs:anyAttribute/>
  </xs:complexType>
</xs:element>
现在，我们希望通过 "gender" 属性来扩展 "person" 元素。在这种情况下我们就可以这样做，即使这个 schema 的作者从未声明过任何 "gender" 属性。

请看这个 schema 文件，名为 "attribute.xsd"：

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">

<xs:attribute name="gender">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:pattern value="male|female"/>
    </xs:restriction>
  </xs:simpleType>
</xs:attribute>

</xs:schema>
下面这个 XML（名为 "Myfamily.xml"），使用了来自不同 schema 的成分，"family.xsd" 和 "attribute.xsd"：

<?xml version="1.0" encoding="ISO-8859-1"?>

<persons xmlns="http://www.microsoft.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.microsoft.com family.xsd
http://www.w3school.com.cn attribute.xsd">

  <person gender="female">
    <firstname>Jane</firstname>
    <lastname>Smith</lastname>
  </person>

  <person gender="male">
    <firstname>David</firstname>
    <lastname>Smith</lastname>
  </person>

</persons>
上面这个 XML 文件是有效的，这是因为 schema "family.xsd" 允许我们向 "person" 元素添加属性。

<any> 和 <anyAttribute> 均可用于制作可扩展的文档！它们使文档有能力包含未在主 XML schema 中声明过的附加元素。


【XSD 元素替换（Element Substitution）】

通过 XML Schema，一个元素可对另一个元素进行替换。

●元素替换
让我们举例说明：我们的用户来自英国和挪威。我们希望有能力让用户选择在 XML 文档中使用挪威语的元素名称还是英语的元素名称。

为了解决这个问题，我们可以在 XML schema 中定义一个 substitutionGroup。首先，我们声明主元素，然后我们会声明次元素，这些次元素可声明它们能够替换主元素。

<xs:element name="name" type="xs:string"/>
<xs:element name="navn" substitutionGroup="name"/>
在上面的例子中，"name" 元素是主元素，而 "navn" 元素可替代 "name" 元素。

请看一个 XML schema 的片段：

<xs:element name="name" type="xs:string"/>
<xs:element name="navn" substitutionGroup="name"/>

<xs:complexType name="custinfo">
  <xs:sequence>
    <xs:element ref="name"/>
  </xs:sequence>
</xs:complexType>

<xs:element name="customer" type="custinfo"/>
<xs:element name="kunde" substitutionGroup="customer"/>
有效的 XML 文档类似这样（根据上面的 schema）：

<customer>
  <name>John Smith</name>
</customer>
或类似这样：

<kunde>
  <navn>John Smith</navn>
</kunde>

●阻止元素替换
为防止其他的元素替换某个指定的元素，请使用 block 属性：

<xs:element name="name" type="xs:string" block="substitution"/>
请看某个 XML schema 的片段：

<xs:element name="name" type="xs:string" block="substitution"/>
<xs:element name="navn" substitutionGroup="name"/>

<xs:complexType name="custinfo">
  <xs:sequence>
    <xs:element ref="name"/>
  </xs:sequence>
</xs:complexType>

<xs:element name="customer" type="custinfo" block="substitution"/>
<xs:element name="kunde" substitutionGroup="customer"/>
合法的 XML 文档应该类似这样（根据上面的 schema）：

<customer>
  <name>John Smith</name>
</customer>
但是下面的文档不再合法：

<kunde>
  <navn>John Smith</navn>
</kunde>

●使用 substitutionGroup
可替换元素的类型必须和主元素相同，或者从主元素衍生而来。假如可替换元素的类型与主元素的类型相同，那么您就不必规定可替换元素的类型了。

请注意，substitutionGroup 中的所有元素（主元素和可替换元素）必须被声明为全局元素，否则就无法工作！

●什么是全局元素（Global Elements）？
全局元素指 "schema" 元素的直接子元素！本地元素（Local elements）指嵌套在其他元素中的元素。


